package com.wgzx.modbus.entity.response;

import com.wgzx.modbus.constant.FunctionCode;
import com.wgzx.modbus.entity.ModbusRsp;
import io.netty.buffer.ByteBuf;
import lombok.Getter;

/**
 * 请求报文：<br/>
 * 功能码：0x03 描述：读取多个寄存器(也有叫"读取保持寄存器"的) <br/>
 * 起始地址：2个字节0x0000至0xFFFF <br/>
 * 寄存器数量：2个字节 范围:1至0x7D <br/>
 * 备注：对象类型16比特(字)，也就是请求1个数据，返回2个字节(16bit) <br/>
 *
 * 响应报文：<br/>
 * 功能码：0x03 <br/>
 * 字节数：1个字节 <br/>
 * 寄存器值：N个字节 <br/>
 *
 * 错误响应：<br/>
 * 差错码：1个字节0x83 <br/>
 * 异常码：1个字节01或02或03或04 <br/>
 *
 * 测试报文：<br/>
 * Rx:00 01(事务ID) 00 00(协议标识) 00 06(长度) FF(单元标识符) 03(功能码) 00 00(起始地址) 00 0A(寄存器数量,请求读取10个数据) <br/>
 * Tx:00 01 00 00 00 17 FF 03 14(长度=十进制20) 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 00 0A(响应返回10个寄存器数据，20个字节) <br/>
 * ps：读取多个寄存器，需要获取数据的长度=10，所以返回了20个字节。<br/>
 *
 * Rx:00 01(事务ID) 00 00(协议标识) 00 06(长度) FF(单元标识符) 03(功能码) 00 02(起始位置偏移量) 00 06(请求读取6个数据) <br/>
 * Tx:00 01(事务ID) 00 00(协议标识) 00 0F(长度) FF(单元标识符) 03(功能码) 0C(数据长度=12) 00 03 00 04 00 05 00 06 00 07 00 08（响应返回6个数据，12个字节）<br/>
 *
 * @author gexin
 */
@Getter
public class ReadHoldingRegistersResponse extends ModbusRsp {

    private short byteCount;
    private int[] registers;

    public ReadHoldingRegistersResponse(FunctionCode functionCode) {
        super(functionCode);
    }

    @Override
    public void decode(ByteBuf data) {
        //解码数据长度。
        byteCount = data.readUnsignedByte();
        //每2个字节表示一个寄存器的值。
        registers = new int[byteCount >> 1];
        for (int i = 0; i < registers.length; i++) {
            registers[i] = data.readUnsignedShort();
        }
    }

    @Override
    public String toString() {
        StringBuilder registersStr = new StringBuilder();
        registersStr.append("{");
        for (int i = 0; i < registers.length; i++) {
            registersStr.append("register_");
            registersStr.append(i);
            registersStr.append("=");
            registersStr.append(registers[i]);
            registersStr.append(", ");
        }
        registersStr.delete(registersStr.length() - 2, registersStr.length());
        registersStr.append("}");

        return "ReadHoldingRegistersResponse{" + "byteCount=" + byteCount + ", inputRegisters=" + registersStr + '}';
    }
}
